package jmind.core.redis;

import com.alibaba.fastjson.JSON;
import jmind.base.lang.ScoreValue;
import jmind.base.util.DataUtil;
import jmind.base.util.MethodUtil;
import jmind.core.log.LogUtil;
import redis.clients.jedis.ListPosition;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.Tuple;
import redis.clients.jedis.commands.JedisClusterCommands;

import java.util.*;

/**
 * redis 操作基类  兼容2.9及一下版本 。3.0 以上请用AbstractJedis
 * http://manual.csser.com/redis/index.html
 * @author weibo-xie
 * 2012-11-6
 */
public abstract class AbstractJedis implements Redis {

    public abstract JedisClusterCommands getResource();

    /**
     * 万能操作入口
     * @param method
     * @param args
     * @return
     */
    public Object execute(String method, Object... args) {
        JedisClusterCommands jedis = getResource();
        try {
            return MethodUtil.invokeMethod(jedis, method, args);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }

    }

    /**
     * 判断某个key 是否存在
     * @param key
     * @return
     */
    public Boolean exists(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            Boolean exists = jedis.exists(key);
            return exists;
        } catch (Exception e) {
            LogUtil.error(e);
            return false;
        } finally {
            close(jedis);
        }
    }

    public String set(String key, String val) {
        JedisClusterCommands jedis = null;
        try {
            jedis = getResource();
            String string = jedis.set(key, val);
            return string;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    public String get(String key) {
        JedisClusterCommands jedis = null;
        try {
            jedis = getResource();
            return jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    /**
     * 设置过期时间
     * @param key
     * @param seconds
     * @return 1 成功 0 失败
     */
    public boolean expire(String key, int seconds) {
        JedisClusterCommands jedis = getResource();
        try {
            Long expire = jedis.expire(key, seconds);
            return expire == 1L;
        } finally {
            close(jedis);
        }
    }

    public long inc(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            Long val = jedis.incr(key);
            return val;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            close(jedis);
        }
    }

    /***********************list***************************/
    public Long lpush(String key, String... str) {
        JedisClusterCommands jedis = getResource();
        Long l = 0l;
        try {
            l = jedis.lpush(key, str);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.log.error("lpush err, len={}, first={} ,key=" + key, str.length, str[0]);
        } finally {
            close(jedis);
        }
        return l;
    }

    public Long rpush(String key, String... str) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.rpush(key, str);
        } catch (Exception e) {
            LogUtil.log.error("lpush err, key={},len={}, first={} ,{}", key, str.length, str[0], e);
        } finally {
            close(jedis);
        }
        return 0l;
    }

    /**
     * 
     * @param key
     * @param pageNo 页数,从第一页开始
     * @param length 条数
     * @return
     */
    public List<String> lrangePage(String key, int pageNo, int length) {
        JedisClusterCommands jedis = getResource();
        try {
            int k = pageNo * length;
            List<String> list = jedis.lrange(key, k - length, k - 1);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return Collections.emptyList();
        } finally {
            close(jedis);
        }

    }

    /**
     * list 长度
     * @param key
     * @return
     */
    public Long llen(String key) {
        JedisClusterCommands jedis = getResource();

        try {
            return jedis.llen(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0l;
        } finally {
            close(jedis);
        }
    }

    /**************zset********************/
    /**
     * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
    如果某个 member 已经是有序集的成员，那么更新这个 member 的 score 值，并通过重新插入这个 member 元素，来保证该 member 在正确的位置上。
    score 值可以是整数值或双精度浮点数。
    如果 key 不存在，则创建一个空的有序集并执行 ZADD 操作。
    当 key 存在但不是有序集类型时，返回一个错误。
     * @param key
     * @param score
     * @param member
     */
    public Long zadd(String key, double score, String member) {
        JedisClusterCommands jedis = getResource();

        try {
            return jedis.zadd(key, score, member);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(jedis);
        }
        return 0l;

    }

    /**
     * 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略。
    当 key 存在但不是有序集类型时，返回一个错误。
     * @param key
     * @param member
     * @return 
     */
    public Long zrem(String key, String... member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zrem(key, member);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(jedis);
        }
        return 0l;
    }

    /**
     * 返回有序集 key 的计数。
     * @param key
     * @return 
     */
    public Long zcard(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zcard(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0l;
        } finally {
            close(jedis);
        }
    }

    /**
     * 返回有序集 key 中， score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员。
    关于参数 min 和 max 的详细使用方法，请参考 ZRANGEBYSCORE 命令。
     * @param key
     * @param
     * @return 
     */
    public Long zcount(String key, double min, double max) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zcount(key, min, max);
        } catch (Exception e) {
            e.printStackTrace();
            return (long) 0;
        } finally {
            close(jedis);
        }
    }

    /**
     * 返回有序集 key 中，成员 member 的 score 值。
    如果 member 元素不是有序集 key 的成员，或 key 不存在，返回 nil 。
     * @param key
     * @param member
     * @return
     */
    public Double zscore(String key, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zscore(key, member);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    /**
    为有序集 key 的成员 member 的 score 值加上增量 increment 。
    可以通过传递一个负数值 increment ，让 score 减去相应的值，比如 ZINCRBY key -5 member ，就是让 member 的 score 值减去 5 。
    当 key 不存在，或 member 不是 key 的成员时， ZINCRBY key increment member 等同于 ZADD key increment member 。
    当 key 不是有序集类型时，返回一个错误。
    score 值可以是整数值或双精度浮点数。
     */
    public double zincby(String key, double score, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zincrby(key, score, member);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            close(jedis);
        }
    }

    /**
     * 返回有序集 key 中，指定区间内的成员。
    其中成员的位置按 score 值递增(从小到大)来排序。
    具有相同 score 值的成员按字典序(lexicographical order )来排列。
    如果你需要成员按 score 值递减(从大到小)来排列，请使用 ZREVRANGE 命令。
    下标参数 start 和 stop 都以 0 为底，也就是说，以 0 表示有序集第一个成员，以 1 表示有序集第二个成员，以此类推。
    你也可以使用负数下标，以 -1 表示最后一个成员， -2 表示倒数第二个成员，以此类推。
    超出范围的下标并不会引起错误。
    比如说，当 start 的值比有序集的最大下标还要大，或是 start > stop 时， ZRANGE 命令只是简单地返回一个空列表。
    另一方面，假如 stop 参数的值比有序集的最大下标还要大，那么 Redis 将 stop 当作最大下标来处理。
    可以通过使用 WITHSCORES 选项，来让成员和它的 score 值一并返回，返回列表以 value1,score1, ..., valueN,scoreN 的格式表示。
    客户端库可能会返回一些更复杂的数据类型，比如数组、元组等。
     * @param key
     * @param start
     * @param end
     * @return 
     */
    public List<String> zrange(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<String> set = jedis.zrange(key, start, end);
            return new ArrayList<String>(set);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    public List<String> zrevrange(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrevrange(key, start, end));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
    具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的，不需要额外的计算)。
    可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count )，注意当 offset 很大时，定位 offset 的操作可能需要遍历整个有序集，此过程最坏复杂度为 O(N) 时间。
    可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员，还是将有序集成员及其 score 值一起返回。
    该选项自 Redis 2.0 版本起可用。
     * @param key
     * @param min
     * @param max
     * @return
     */
    public List<String> zrangeByScore(String key, double min, double max) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrangeByScore(key, min, max));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    /**
     * 返回有序集 key 中， score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
    具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。
    除了成员按 score 值递减的次序排列这一点外， ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一样。
     * @param key
     * @param min
     * @param max
     * @return
     */
    public List<String> zrevrangeByScore(String key, double max, double min) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrevrangeByScore(key, max, min));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            close(jedis);
        }
    }

    /**
     * 移除有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。
        自版本2.1.6开始， score 值等于 min 或 max 的成员也可以不包括在内，详情请参见 ZRANGEBYSCORE 命令。
     * @param key
     * @param min
     * @param max
     * @return 被移除成员的数量。
     */
    public Long zremrangeByScore(String key, double min, double max) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zremrangeByScore(key, min, max);
        } catch (Exception e) {
            e.printStackTrace();
            return 0l;
        } finally {
            close(jedis);
        }

    }

    /**
     *  移除有序集 key 中，指定排名(rank)区间内的所有成员。

        区间分别以下标参数 start 和 stop 指出，包含 start 和 stop 在内。

        下标参数 start 和 stop 都以 0 为底，也就是说，以 0 表示有序集第一个成员，以 1 表示有序集第二个成员，以此类推。
        你也可以使用负数下标，以 -1 表示最后一个成员， -2 表示倒数第二个成员，以此类推。
     * @param key
     * @param start
     * @param end
     * @return 被移除成员的数量。
     */
    public long zremrangeByRank(String key, int start, int end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zremrangeByRank(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            close(jedis);
        }

    }

    @Override
    public String type(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.type(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public boolean expireAt(String key, long unixTime) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.expireAt(key, unixTime) == 1;

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long ttl(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.ttl(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long setbit(String key, long offset, int value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.setbit(key, offset, value == 1) ? 1l : 0;

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long getbit(String key, long offset) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.getbit(key, offset) ? 1l : 0;

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long setrange(String key, long offset, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.setrange(key, offset, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String getrange(String key, long startOffset, long endOffset) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.getrange(key, startOffset, endOffset);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String getSet(String key, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.getSet(key, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long setnx(String key, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.setnx(key, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String setex(String key, int seconds, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.setex(key, seconds, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long decrBy(String key, long integer) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.decrBy(key, integer);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long decr(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.decr(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long incrBy(String key, long integer) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.incrBy(key, integer);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long incr(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.incr(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long append(String key, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.append(key, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String substr(String key, int start, int end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.substr(key, start, end);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long hset(String key, String field, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hset(key, field, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String hget(String key, String field) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hget(key, field);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long hsetnx(String key, String field, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hsetnx(key, field, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String hmset(String key, Map<String, String> hash) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hmset(key, hash);

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> hmget(String key, String... fields) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hmget(key, fields);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long hincrBy(String key, String field, long value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hincrBy(key, field, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Boolean hexists(String key, String field) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hexists(key, field);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long hdel(String key, String... field) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hdel(key, field);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long hlen(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hlen(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Set<String> hkeys(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hkeys(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> hvals(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hvals(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Map<String, String> hgetAll(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.hgetAll(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> lrange(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lrange(key, start, end);

        } finally {
            close(jedis);
        }
    }

    public List<String> lrevrange(String key, long start, long end) {
        long s = end + 1;
        long e = start + 1;
        return this.lrange(key, -s, -e);
    }

    @Override
    public String ltrim(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.ltrim(key, start, end);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String lindex(String key, long index) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lindex(key, index);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String lset(String key, long index, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lset(key, index, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long lrem(String key, long count, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lrem(key, count, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String lpop(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lpop(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String rpop(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.rpop(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long sadd(String key, String... member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.sadd(key, member);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Set<String> smembers(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.smembers(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long srem(String key, String... member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.srem(key, member);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String spop(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.spop(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long scard(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.scard(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Boolean sismember(String key, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.sismember(key, member);

        } finally {
            close(jedis);
        }
    }

    @Override
    public String srandmember(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.srandmember(key);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long zadd(String key, Map<String, Double> scoreMembers) {
        JedisClusterCommands jedis = getResource();
        try {

            return jedis.zadd(key, scoreMembers);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Double zincrby(String key, double score, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zincrby(key, score, member);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long zrank(String key, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zrank(key, member);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long zrevrank(String key, String member) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zrevrank(key, member);

        } finally {
            close(jedis);
        }
    }

    public List<ScoreValue<String>> zrangeWithScores(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> zrangeWithScores = jedis.zrangeWithScores(key, start, end);
            return formart(zrangeWithScores);
        } finally {
            close(jedis);
        }
    }

    @Override
    public List<ScoreValue<String>> zrangeByScoreWithScores(String key, double min, double max) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> zrangeWithScores = jedis.zrangeByScoreWithScores(key, min, max);
            return formart(zrangeWithScores);
        } finally {
            close(jedis);
        }
    }

    @Override
    public List<ScoreValue<String>> zrevrangeByScoreWithScores(String key, double max, double min) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> zrangeWithScores = jedis.zrevrangeByScoreWithScores(key, max, min);
            return formart(zrangeWithScores);
        } finally {
            close(jedis);
        }
    }

    @Override
    public List<ScoreValue<String>> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> zrangeWithScores = jedis.zrangeByScoreWithScores(key, min, max, offset, count);
            return formart(zrangeWithScores);
        } finally {
            close(jedis);
        }
    }

    @Override
    public List<ScoreValue<String>> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> zrangeWithScores = jedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
            return formart(zrangeWithScores);
        } finally {
            close(jedis);
        }
    }

    private List<ScoreValue<String>> formart(Set<Tuple> set) {
        List<ScoreValue<String>> list = new ArrayList<ScoreValue<String>>();
        for (Tuple tuple : set) {
            list.add(new ScoreValue<String>(tuple.getScore(), tuple.getElement()));
        }
        Collections.sort(list);
        return list;
    }

    public List<ScoreValue<String>> zrevrangeWithScores(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            Set<Tuple> set = jedis.zrevrangeWithScores(key, start, end);
            return formart(set);
        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> sort(String key) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.sort(key);

        } finally {
            close(jedis);
        }
    }

    public List<String> sort(String key, SortingParams sortingParameters) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.sort(key, sortingParameters);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long zcount(String key, String min, String max) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zcount(key, min, max);

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> zrangeByScore(String key, String min, String max) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrangeByScore(key, min, max));

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> zrangeByScore(String key, double min, double max, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrangeByScore(key, min, max, offset, count));

        } finally {
            close(jedis);
        }
    }

    public List<String> zrevrangeByScore(String key, String max, String min) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrevrangeByScore(key, max, min));

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> zrangeByScore(String key, String min, String max, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrangeByScore(key, min, max, offset, count));

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> zrevrangeByScore(String key, double max, double min, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrevrangeByScore(key, max, min, offset, count));

        } finally {
            close(jedis);
        }
    }

    @Override
    public List<String> zrevrangeByScore(String key, String max, String min, int offset, int count) {
        JedisClusterCommands jedis = getResource();
        try {
            return new ArrayList<String>(jedis.zrevrangeByScore(key, max, min, offset, count));

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long zremrangeByRank(String key, long start, long end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zremrangeByRank(key, start, end);

        } finally {
            close(jedis);
        }
    }

    public Long zremrangeByScore(String key, String start, String end) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.zremrangeByScore(key, start, end);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long linsert(String key, boolean before, String pivot, String value) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.linsert(key, before ? ListPosition.BEFORE : ListPosition.AFTER, pivot, value);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long lpushx(String key, String string) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.lpushx(key, string);

        } finally {
            close(jedis);
        }
    }

    @Override
    public Long rpushx(String key, String string) {
        JedisClusterCommands jedis = getResource();
        try {
            return jedis.rpushx(key, string);

        } finally {
            close(jedis);
        }
    }

    public boolean setObject(String key, Object o) {
        if(o==null || key==null ){
            return false;
        }
        String value= o instanceof String? (String)o:JSON.toJSONString(o);
        String setObjectRet = set(key, value);
        return "OK".equalsIgnoreCase(setObjectRet);

    }

    public boolean setObject(String key,int seconds, Object o) {
        if(o==null || key==null){
            return false;
        }
        String value= o instanceof String? (String)o:JSON.toJSONString(o);
        String setObjectRet = setex(key,seconds,value);
        return "OK".equalsIgnoreCase(setObjectRet);
    }

    public <T> T getObject(String key, Class<T> clazz) {
        String string = get(key);
        if (DataUtil.isEmpty(string))
            return null;
        if(String.class.equals(clazz)){
            return (T) string;
        }
        return JSON.parseObject(string, clazz);
    }

    public <T> List<T> getArray(String key,Class<T> clazz){
        String s=get(key);
        return JSON.parseArray(s,clazz);
    }

}
